package com.yyl.rbacs.annotation;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yyl.rbacs.sys.entity.SysRoleDept;
import com.yyl.rbacs.sys.entity.SysUser;
import com.yyl.rbacs.sys.entity.SysUserRole;
import com.yyl.rbacs.sys.service.ISysDeptService;
import com.yyl.rbacs.sys.service.ISysRoleDeptService;
import com.yyl.rbacs.sys.service.ISysUserRoleService;
import com.yyl.rbacs.utils.Constants;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @BelongsProject: rbacs
 * @BelongsPackage: com.yyl.rbacs.annotation
 * @Author: YuanSir
 * @CreateTime: 2022-11-02  09:53
 * @Description:
 * @Version: 1.0
 */


@Component
@Aspect
public class DataFilterAspect {
    
    @Autowired
    ISysUserRoleService userRoleService;
    
    @Autowired
    ISysRoleDeptService roleDeptService;
    
    @Autowired
    ISysDeptService deptService;
    
    //定义切点，该切点切的是加了DataFilter注解的方法
    @Pointcut("@annotation(com.yyl.rbacs.annotation.DataFilter)")
    public void pointCut() {
    }
    
    
    @Before("pointCut()")
    public void before(JoinPoint jp) {
        
        //把过滤数据权限的sql片段，添加到当前方法的第一个参数（第一个参数约定必须是map类型）
        
        // 通过joinPoint获取方法签名对象
        
        
        MethodSignature signature = (MethodSignature) jp.getSignature();
        
        Method method = signature.getMethod();
        
        DataFilter annotation = method.getAnnotation(DataFilter.class);
        
        String dataField = annotation.dataField();
    
        String deptStr = getDeptStr();
    
        //通过反射api获取dataFilter注解中的配置数据库部门id对应的字段名称
        Object[] args = jp.getArgs();
        Object arg = args[0];
    
        if (deptStr == null) { //如果是超级管理员这里直接返回即可
            return;
        }
        
        if (deptStr.equals("()")){ //说明当前用户没有任何数据权限
    
            ((Map) arg).put(Constants.DATA_FILTER, "("+dataField+" in (-1))");
            
            return;
            
        }
    
        //再查询该角色拥有哪些部门ID
        String sql = "(" + dataField + " in " + deptStr + ")";
        
        
        
        
        if (arg != null && arg instanceof Map) {
            ((Map) arg).put(Constants.DATA_FILTER, sql);
        }
    }
    
    /**
     * 获取当前登录用户的数据权限字符串
     * 如果是管理员直接获取全部部门信息
     * 如果非管理员只获取有权限的部门信息
     */
    private String getDeptStr() {
        
        SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();
        
        if (user.getUserId().equals(Constants.SUPER_ADMIN_ID)){
//            List<SysDept> deptList = deptService.list();
//
//            // List<SysDept> ——> Stream<部门ID> ——> (1,2,3,4)
//
//            return deptList.stream()
//                    .map(dept -> dept.getDeptId() + "")
//                    .collect(Collectors.joining(",", "(", ")"));
            return null;
        }
        //根据当前登录用户查询用户的角色
        List<Object> roleIdList = userRoleService.listObjs(new LambdaQueryWrapper<SysUserRole>()
                .select(SysUserRole::getRoleId)
                .eq(SysUserRole::getUserId, user.getUserId()));
        
        //再查询该角色拥有哪些部门ID
        String deptStr = roleDeptService.listObjs(new LambdaQueryWrapper<SysRoleDept>()
                        .select(SysRoleDept::getDeptId)
                        .in(SysRoleDept::getRoleId, roleIdList))
                .stream()
                .map(String::valueOf)
                .collect(Collectors.joining(",", "(", ")"));
        
        return deptStr;
    }
}
